/*
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * Copyright 2016-2020 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#ifndef _FSL_LPI2C_H_
#define _FSL_LPI2C_H_

#include "fsl_common.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/* transfer flags. */
#define LPI2C_TRANSFER_FLAG_READ    (1u << 0)
#define LPI2C_TRANSFER_FLAG_RESTART (1u << 1) /* Send RESTART instead of START at the beginning of transfer. */
#define LPI2C_TRANSFER_FLAG_NO_STOP (1u << 2)


/* master status flags, also for interrupt status. */
#define LPI2C_MASTER_STATUS_TxReady         LPI2C_MSR_TDF_MASK  /*!< Transmit data flag. */
#define LPI2C_MASTER_STATUS_RxReady         LPI2C_MSR_RDF_MASK  /*!< Receive data flag. */
#define LPI2C_MASTER_STATUS_EndOfPacket     LPI2C_MSR_EPF_MASK  /*!< End Packet flag. */
#define LPI2C_MASTER_STATUS_StopDetect      LPI2C_MSR_SDF_MASK  /*!< Stop detect flag. */
#define LPI2C_MASTER_STATUS_NackDetect      LPI2C_MSR_NDF_MASK  /*!< NACK detect flag. */
#define LPI2C_MASTER_STATUS_ArbitrationLost LPI2C_MSR_ALF_MASK  /*!< Arbitration lost flag. */
#define LPI2C_MASTER_STATUS_FifoErr         LPI2C_MSR_FEF_MASK  /*!< FIFO error flag. */
#define LPI2C_MASTER_STATUS_PinLowTimeout   LPI2C_MSR_PLTF_MASK /*!< Pin low timeout flag. */
#define LPI2C_MASTER_STATUS_DataMatch       LPI2C_MSR_DMF_MASK  /*!< Data match flag. */
#define LPI2C_MASTER_STATUS_Busy            LPI2C_MSR_MBF_MASK  /*!< Master busy flag. */
#define LPI2C_MASTER_STATUS_BusBusy         LPI2C_MSR_BBF_MASK  /*!< Bus busy flag. */

/* DMA. */
#define LPI2C_MASTER_DMA_TX               LPI2C_MDER_TDDE_MASK
#define LPI2C_MASTER_DMA_RX               LPI2C_MDER_RDDE_MASK

#define LPI2C_MASTER_TX_FIFO_COUNT_MAX    4u

#define LPI2C_MASTER_TRANSFER_FLAG_Write    (0u)        /* write direction by default, with start and stop, considerting the first tx byte as target device address. */
#define LPI2C_MASTER_TRANSFER_FLAG_Read     (1u << 0u)
#define LPI2C_MASTER_TRANSFER_FLAG_NoStart  (1u << 1u)
#define LPI2C_MASTER_TRANSFER_FLAG_NoStop   (1u << 2u) /* Do not send STOP at the end of transfer. */


typedef enum
{
    eLPI2C_ClockCycleDiv_1 = 0u,
    eLPI2C_ClockCycleDiv_2 = 1u,
    eLPI2C_ClockCycleDiv_4 = 2u,
    eLPI2C_ClockCycleDiv_8 = 3u,
    eLPI2C_ClockCycleDiv_16 = 4u,
    eLPI2C_ClockCycleDiv_32 = 5u,
    eLPI2C_ClockCycleDiv_64 = 6u,
    eLPI2C_ClockCycleDiv_128 = 7u,
} LPI2C_ClockCycleDiv_Type;

typedef struct
{
    uint8_t DataValidDelayCycles; /*!< Minimum number of cycles (minus one) that is used as the data hold time for SDA. */
    uint8_t SetupHoldDelayCycles;    /*!< for generating (repeat) START and STOP. */
    uint8_t ClockHighPeriodCycles;   /*!< Minimum number of cycles (minus one) that the SCL clock is driven high by the master. */
    uint8_t ClockLowPeriodCycles;    /*!< Minimum number of cycles (minus one) that the SCL clock is driven low by the master. */
} LPI2C_ClockConf_Type;



typedef struct
{
    uint32_t BaudrateHz;

    uint32_t TxFifoWatermark; /* The Tx flag would be asserted when Tx data is more then this count. */
    uint32_t RxFifoWatermark; /* The Rx flag would be asserted when Tx data is more then this count. */

    /* hardware automatiation settings. */
    bool EnableInDozenMode;
    bool EnableInDebugMode;
    bool EnableIgnoreAck;
    bool EnableAutoGenSTOP; /* STOP condition is automatically generated whenever the transmit FIFO is empty and LPI2C master is busy. */

    /* timing settings. */
    LPI2C_ClockCycleDiv_Type ClockCycleDiv; /* Configures the clock prescaler used for all LPI2C master logic, except the digital glitch filters. */
    uint32_t BusIdleTimeoutCycles; /* 12bit. 0 to disable. */


    LPI2C_ClockConf_Type * ClockConf;
} LPI2C_MasterConf_Type;


typedef enum
{
    eLPI2C_TxFifoCmd_TxData = 0U, /* Transmit DATA[7:0]. */
    eLPI2C_TxFifoCmd_RxCountOfNplus1Byte = 1U, /* Receive (DATA[7:0] + 1) bytes. */
    eLPI2C_TxFifoCmd_GenerateSTOP = 2U, /* Generate STOP condition. */

    /* Receive and discard (DATA[7:0] + 1) bytes. */
    eLPI2C_TxFifoCmd_RxAndDiscardCountOfNplus1Byte = 3U,

    /* Generate (repeated) START and transmit address in DATA[7:0]. */
    eLPI2C_TxFifoCmd_GenerateSTARTAndSendAddrByte = 4U,

    /*
    * Generate (repeated) START and transmit address in DATA[7:0].
    * This transfer expects a NACK to returned.
    */
    eLPI2C_TxFifoCmd_GenerateSTARTAndSendAddrByteWithNACKBack = 5U,

    /*
    * Generate (repeated) START and transmit address in DATA[7:0]
    * using high speed mode.
    */
    eLPI2C_TxFifoCmd_GenerateSTARTAndSendAddrByteInHighSpeed = 6U,

    /*
    * Generate (repeated) START and transmit address in DATA[7:0]
    * using high speed mode. This transfer expects a NACK to be returned.
    */
    eLPI2C_TxFifoCmd_GenerateSTARTAndSendAddrByteWithNACKBackInHighSpeed = 7U,
} LPI2C_TxFifoCmd_Type;



void     LPI2C_MasterInit(LPI2C_Type * LPI2Cx, LPI2C_MasterConf_Type * conf, uint32_t src_clk_hz);
void     LPI2C_MasterWriteTxFifoCmd(LPI2C_Type *LPI2Cx, LPI2C_TxFifoCmd_Type cmd, uint8_t data);
bool     LPI2C_MasterReadRxFifoData(LPI2C_Type *LPI2Cx, uint8_t *data);
uint32_t LPI2C_MasterGetStatusFlags(LPI2C_Type *LPI2Cx);
void     LPI2C_MasterClearStatusFlags(LPI2C_Type *LPI2Cx, uint32_t flags);
void     LPI2C_MasterEnableInterrupts(LPI2C_Type *LPI2Cx, uint32_t flags);
void     LPI2C_MasterDisableInterrupts(LPI2C_Type *LPI2Cx, uint32_t flags);
uint32_t LPI2C_MasterGetEnabledInterrupts(LPI2C_Type *LPI2Cx);
void     LPI2C_MasterEnableDMA(LPI2C_Type *LPI2Cx, uint32_t flags);
uint32_t LPI2C_MasterGetTxFifiCount(LPI2C_Type * LPI2Cx);
uint32_t LPI2C_MasterWriteBlocking(LPI2C_Type *LPI2Cx, uint8_t addr, uint8_t *buf, uint32_t len, uint32_t flags);
uint32_t LPI2C_MasterReadBlocking(LPI2C_Type *LPI2Cx, uint8_t addr, uint8_t *buf, uint32_t len, uint32_t flags);

uint32_t LPI2C_MasterTransferBlocking(LPI2C_Type *LPI2Cx, uint8_t addr, uint8_t *buf, uint32_t buf_len, uint32_t flags);
uint32_t LPI2C_MasterTransferBlocking2(LPI2C_Type *LPI2Cx, uint8_t *buf, uint32_t buf_len, uint32_t flags);
int32_t LPI2C_MasterWriteBlockingTimeout(LPI2C_Type *LPI2Cx, uint8_t addr, uint8_t *buf, uint32_t len, uint32_t flags, uint32_t timeout);
int32_t LPI2C_MasterReadBlockingTimeout(LPI2C_Type *LPI2Cx, uint8_t addr, uint8_t *buf, uint32_t len, uint32_t flags, uint32_t timeout);


#endif /* _FSL_LPI2C_H_ */
